package com.guzhi.service.huanxin.impl;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.guzhi.common.Consts;
import com.guzhi.common.HXConstants;
import com.guzhi.domain.hx.EndPoints;
import com.guzhi.domain.hx.request.ChatgroupsReq;
import com.guzhi.domain.hx.request.MessageReq;
import com.guzhi.domain.hx.request.MsgReq;
import com.guzhi.domain.hx.request.TokenReq;
import com.guzhi.domain.hx.response.ChatGroupResp;
import com.guzhi.domain.hx.response.TokenResp;
import com.guzhi.domain.hx.response.UserResp;
import com.guzhi.exception.GZException;
import com.guzhi.mapper.AdminMapper;
import com.guzhi.service.RedisService;
import com.guzhi.service.huanxin.HXIService;
import com.guzhi.utils.HttpClientHelper;
import com.guzhi.utils.JsonHelper;

/**
 * author Elson
 * 2014年11月6日
 * email 372069412@qq.com
 */
@Service
public class HXServiceImpl implements HXIService {

    private final Logger LOG = LoggerFactory.getLogger(HXServiceImpl.class);

    @Autowired(required = true)
    private RedisService redis;

    @Autowired(required = true)
    private AdminMapper adminMapper;

    /**
     * 环信注册用户
     * 
     * @param userName 帐号
     * @param password 密码
     * @return 返回用户的UUID
     * */
    @Override
    public String register(String username, String password,String nick) {

        if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) {
            return null;
        }
        try {
            return registerHelper(username, password,nick);
        } catch (Exception e) {
            LOG.error("register error , will retry ,username:{}", username, e);
            // 等100ms后,重试,外部接口增加重试,保证稳定性
            try {
                TimeUnit.MILLISECONDS.sleep(100);
            } catch (InterruptedException e1) {
            }
            return registerHelper(username, password,nick);
        }
    }

    /**
     * 注册环信用户辅助方法
     * 
     * @param username md5加密后的手机号
     * @param pwd　MD5
     * @return
     */
    private String registerHelper(String username, String pwd,String nick) {
        Map<String, String> parame = new HashMap<String, String>();
        parame.put("nickname", nick);
        parame.put("username", username);
        parame.put("password", pwd);
        Map<String, String> headers = new HashMap<String, String>();
        headers.put("Content-Type", "application/json;charset=utf-8");

        String result = HttpClientHelper.sendRequest(true, EndPoints.getHXregisterUserUrl(), JsonHelper.toJson(parame),
                "utf-8", headers);

        LOG.info("register username:{}, resp:{}", username, result);
        if (result == null) {
            throw new GZException(Consts.Code.NET_CONN_ERROR, "");
        }
        UserResp user = JsonHelper.fromJson(result, UserResp.class);
        if (user == null || user.getEntities() == null || user.getEntities().length <= 0) {
            throw new GZException(Consts.Code.DATA_ERROR, "环信注册失败");
        }
        return user.getEntities()[0].getUsername();
    }

    @Override
    public ChatGroupResp createChatGroup(ChatgroupsReq chatGroup) {

        if (null == chatGroup) {
            return null;
        }
        try {
            return createChatGroupHelper(chatGroup);
        } catch (Exception e) {
            LOG.error("create chatGroup is error", e);
            try {
                TimeUnit.MILLISECONDS.sleep(100);
            } catch (InterruptedException el) {

            }
            return createChatGroupHelper(chatGroup);
        }

    }

    /**
     * 创建环信讨论组辅助方法
     * 
     * @param chatGroup
     **/
    private ChatGroupResp createChatGroupHelper(ChatgroupsReq chatGroup) {
        Map<String, String> headers = new HashMap<>();
        headers.put("Authorization", "Bearer " + getToken());
        String result = HttpClientHelper.sendRequest(true, EndPoints.getChatGroupUrl(), JsonHelper.toJson(chatGroup),
                "utf-8", headers);
        if (null == result) {
            throw new GZException(Consts.Code.NET_CONN_ERROR, "发送返回失败");
        }
        ChatGroupResp chatGroupResp = JsonHelper.fromJson(result, ChatGroupResp.class);
        LOG.info("create chatGroup result:{} , chatGroup:{}", result, chatGroup);
        if (chatGroupResp.getData().getGroupid() <= 0 || null == chatGroupResp.getData().getGroupid()) {
            throw new GZException(Consts.Code.NET_CONN_ERROR, "返回参数失败");
        }
        return chatGroupResp;
    }

    /**
     * 获取环信token值
     * 
     * @param token-Bean
     * @return
     * */
    @Override
    public TokenResp getToken(TokenReq token) {

        if (null == token) {
            return null;
        }
        try {
            return getTokenHelper(token);
        } catch (Exception e) {
            LOG.error("get token error will retry , token", token, e);
            // 等100ms后,重试,外部接口增加重试,保证稳定性
            try {
                TimeUnit.MILLISECONDS.sleep(100); // 重新发一次请求
            } catch (InterruptedException el) {

            }
            return getTokenHelper(token);
        }
    }

    /**
     * 获取token辅助方法
     * 
     * @param token
     * @return
     */
    public TokenResp getTokenHelper(TokenReq token) {
        Map<String, String> headers = new HashMap<>();
        headers.put("Content-Type", "application/json;charset=utf-8");
        String result = HttpClientHelper.sendRequest(true, EndPoints.getTokenUrl(), JsonHelper.toJson(token), "utf-8",
                headers);

        if (result == null) {
            throw new GZException(Consts.Code.NET_CONN_ERROR, "");
        }
        TokenResp tokenResp = JsonHelper.fromJson(result, TokenResp.class);
        if (null == tokenResp || "".equals(tokenResp.getAccess_token())) {
            throw new GZException(Consts.Code.NET_CONN_ERROR, "");
        }
        return tokenResp;
    }

    /**
     * 环信发送透传消息
     * 
     * @param msg
     * */
    @Override
    public String sendMsg(MessageReq msg) {
        if (null == msg) {
            return null;
        }
        try {
            return sendMsgHelper(msg);
        } catch (Exception e) {
            LOG.error("sendMsg error will retry , msg:{}", msg, e);
            try {// 等100ms后,重试,外部接口增加重试,保证稳定性
                TimeUnit.MILLISECONDS.sleep(100);
            } catch (InterruptedException el) {

            }
            return sendMsgHelper(msg);
        }
    }

    /**
     * 环信发送透传消息辅助方法
     * 
     * @param msg
     * */
    private String sendMsgHelper(MessageReq msg) {

        Map<String, String> headers = new HashMap<>();
        headers.put("Content-Type", "application/json;charset=utf-8");
        headers.put("Authorization", "Bearer " + getToken());
        String result = HttpClientHelper.sendRequest(true, EndPoints.getHXSendMsgUrl(), JsonHelper.toJson(msg),
                "utf-8", headers);
        if (StringUtils.isBlank(result)) {
            throw new GZException(Consts.Code.NET_CONN_ERROR, "发送环信透传消息失败");
        }
        return result;
    }

    /**
     * 更新用户环信密码
     * 
     * @param oldPassword
     */
    @Override
    public boolean updateHXPassword(String newPassword, String phone) {
        Map<String, String> map = new HashMap<String, String>();
        map.put("newpassword", newPassword);

        Map<String, String> headers = new HashMap<String, String>();
        headers.put("Authorization", "Bearer " + getToken());

        String result = HttpClientHelper.sendRequest(true, EndPoints.getHXupdatePasswordUrl(phone),
                JsonHelper.toJson(map), "utf-8", headers);
        if (null != result) {
            LOG.info("update password :{}, resp:{}", newPassword);
            return true;
        }
        return false;
    }

    private String getToken() {
        String token = redis.getString(Consts.HXCONSTS.TOKEN);
        if (StringUtils.isBlank(token)) {

            TokenReq req = new TokenReq();
            req.setClient_id(HXConstants.APP_CLIENT_ID);
            req.setClient_secret(HXConstants.APP_CLIENT_SECRET);
            req.setGrant_type("client_credentials");
            TokenResp resp = getToken(req);
            if (resp != null) {
                token = resp.getAccess_token();
                redis.setString(Consts.HXCONSTS.TOKEN, token, (int) (resp.getExpires_in() - 60 * 60 * 24));
            }
        }
        return token;
    }

    /**
     * 查看用户在线状态
     */
    @Override
    public boolean onlineStatus(String username) {

        Map<String, String> map = new HashMap<String, String>();
        map.put("username", username);
        Map<String, String> headers = new HashMap<String, String>();
        headers.put("Content-Type", "application/json");
        headers.put("Authorization", "Bearer " + getToken());
        String result = HttpClientHelper.sendRequest(false, EndPoints.getOnlineStatusUrl(username),
                JsonHelper.toJson(map), "utf-8", headers);
        LOG.info("onlineStatus:", result);
        if (null != result) {
            LOG.info("result :{}, resp:{}", result);
            return true;
        }
        return false;
    }

    /**
     * 统计在线用户数
     */
    @Override
    public Long countOnlineUsers() {

        /*
         * Map<String, String> userList = new HashMap<String, String>();
         * 
         * Long all = adminMapper.countAllUsers();
         * String phone[] = adminMapper.getPhones();
         * int count = 0;
         * for(int i = 0; i < all; i++){
         * boolean online = onlineStatus(CryptUtil.md5(phone[i]));
         * if(online){
         * count++;
         * }
         * }
         */
        return null;
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.guzhi.service.huanxin.HXIService#sendMsg(java.lang.String,
     * java.lang.String[], java.lang.String, com.guzhi.domain.hx.request.ExtReq)
     */
    @Override
    public boolean sendMsg(String from, String[] to, String action, Map<String, Object> ext) {
        MessageReq msg = new MessageReq();
        MsgReq m = new MsgReq();

        m.setType("cmd");
        m.setAction(action);

        msg.setTarget_type("users");
        msg.setTarget(to);
        msg.setMsg(m);
        msg.setFrom(from);
        msg.setExt(ext);
        try {
            String result = sendMsg(msg);
            return StringUtils.contains(result, "success");
        } catch (Exception e) {
            LOG.error("sendMsg error; from:{},to:{},action:{}", from, to, action);
        }
        return false;
    }
    
   
}
